﻿
namespace Patterns4Net.ArchitectureExplorer.ViewModels.Graph
{
    using System.Collections.Generic;
    using System.Linq;
    using Caliburn.Micro;
    using Patterns4Net.ArchitectureExplorer.Diagram;
    using Patterns4Net.Core.AbstractionLevel;
    using Patterns4Net.Core;

    /// <summary>
    /// Provides wrapper for <see cref="TypeInfo"/> diagram element.
    /// The wrapper provides some additional properties that are used in view.
    /// </summary>
    public class TypeInfoViewModel : VertexViewModel
    {
        private readonly GraphViewModel graph;

        private readonly TypeInfo typeInfo;

        public TypeInfoViewModel(
            GraphViewModel graph,
            TypeInfo typeInfo, 
            IEventAggregator eventAggregator)
            : base(typeInfo, eventAggregator)
        {
            this.graph = graph;
            this.typeInfo = typeInfo;
            this.ShowMembers = false;
            this.ShowExpanded = false;
        }

        public override object ContentViewModel
        {
            get
            {
                return this;
            }
        }

        public bool ShowMembers { get; set; }

        public string Name
        {
            get { return this.DiagramElement.Name; }
        }

        public bool ShowExpanded { get; set; }

        public IEnumerable<PropertyInfo> Properties
        {
            get { return this.typeInfo.Properties; }
        }

        public IEnumerable<MethodInfo> Methods
        {
            get { return this.typeInfo.Methods; }
        }

        public IEnumerable<PatternInfo> Patterns
        {
            get
            {
                var result = this.GetAllPatterns().Where(
                    x => x.AbstractionLevel == null || x.AbstractionLevel.Value.IsHigherOrEqual(this.graph.AbstractionLevel));
                return result;
            }
        }

        private IEnumerable<PatternInfo> GetAllPatterns()
        {
            return this.typeInfo.Patterns
                .Concat(this.typeInfo.Methods.SelectMany(m => m.Patterns)
                            .Distinct((p1, p2) => p1.Name == p2.Name));
        }
    }
}
